export class InputManager {
  private keys: Map<string, boolean> = new Map();
  private mouseDelta = { x: 0, y: 0 };
  private mouseButtons: Map<number, boolean> = new Map();
  
  private canvas: HTMLCanvasElement;
  private isPointerLocked = false;

  constructor(canvas: HTMLCanvasElement) {
    this.canvas = canvas;
    this.setupEventListeners();
  }

  private setupEventListeners(): void {
    document.addEventListener('keydown', (e) => this.onKeyDown(e));
    document.addEventListener('keyup', (e) => this.onKeyUp(e));
    
    this.canvas.addEventListener('click', () => this.requestPointerLock());
    document.addEventListener('mousemove', (e) => this.onMouseMove(e));
    this.canvas.addEventListener('mousedown', (e) => this.onMouseDown(e));
    this.canvas.addEventListener('mouseup', (e) => this.onMouseUp(e));
    
    document.addEventListener('pointerlockchange', () => this.onPointerLockChange());
  }

  private onKeyDown(event: KeyboardEvent): void {
    this.keys.set(event.code, true);
    
    // ESC 键解锁鼠标
    if (event.code === 'Escape') {
      if (this.isPointerLocked) {
        document.exitPointerLock();
      }
    }
  }

  private onKeyUp(event: KeyboardEvent): void {
    this.keys.set(event.code, false);
  }

  private onMouseMove(event: MouseEvent): void {
    if (this.isPointerLocked) {
      this.mouseDelta.x = event.movementX;
      this.mouseDelta.y = event.movementY;
    }
  }

  private onMouseDown(event: MouseEvent): void {
    this.mouseButtons.set(event.button, true);
  }

  private onMouseUp(event: MouseEvent): void {
    this.mouseButtons.set(event.button, false);
  }

  private requestPointerLock(): void {
    this.canvas.requestPointerLock();
  }

  private onPointerLockChange(): void {
    this.isPointerLocked = document.pointerLockElement === this.canvas;
  }

  public isKeyPressed(key: string): boolean {
    return this.keys.get(key) || false;
  }

  public isMouseButtonPressed(button: number): boolean {
    return this.mouseButtons.get(button) || false;
  }

  public getMouseDelta(): { x: number; y: number } {
    const delta = { ...this.mouseDelta };
    this.mouseDelta.x = 0;
    this.mouseDelta.y = 0;
    return delta;
  }

  public isPointerLockedActive(): boolean {
    return this.isPointerLocked;
  }
}